package com.lib76.socket.message;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.lib76.socket.Constants;
import com.lib76.socket.model.SocketMessage;
import com.lib76.socket.model.protocol.SocketProtocolObject;
import com.lib76.socket.model.protocol.SocketProtocolParameter;
import com.lib76.utils.JsonUtils;

public class JsonSocketMessage extends SocketMessage{

	private Map<String,Object> header;
	private Map<String,Object> body;
	
	public JsonSocketMessage() {
		super();
	}

	public JsonSocketMessage(SocketProtocolObject protocolObject,
			Object origianlMessage) {
		super(protocolObject, origianlMessage);
	}

	public JsonSocketMessage(Object originalMessage) {
		super(originalMessage);
	}

	public JsonSocketMessage(SocketProtocolObject protocolObject) {
		super(protocolObject);
		
	}
	
	@SuppressWarnings("unchecked")
	public<T> List<T> readList(String name,Class<T> clazz){
		readBody();
		Object obj = this.data.get(name);
		if(obj != null){
			return (List<T>)obj;
		}
		return null;
	}
	
	@SuppressWarnings("rawtypes")
	public void writeMap(String name,Map value){
		this.data.put(name, value);
	}
	
	@SuppressWarnings("rawtypes")
	public void writeList(String name,List value){
		this.data.put(name, value);
	}

	@SuppressWarnings("unchecked")
	public void read(List<SocketProtocolParameter> parameters) throws Exception {
		if(header != null){
			this.data.putAll(header);
			header = null;
		}else if(body != null){
			this.data.putAll(body);
		}else if(this.originalMessageBody != null && this.hasProtocol()){
			if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(this.getProtocolObject().getBodyType())){
				if(StringUtils.isNotBlank(this.originalMessageBody.toString())){
					this.data.putAll(JsonUtils.fromJson(this.originalMessageBody.toString(), Map.class));
				}
			}
		}
	}

	public void write(List<SocketProtocolParameter> parameters)
			throws Exception {
	}

	public Object buildMessage() throws Exception {
		if(this.isOriginalMessageOutput == false && this.hasProtocol()){
			Map<String,Object> header = new HashMap<String,Object>();
			for(SocketProtocolParameter param : this.protocolObject.getHeaderProtocolParameter()){
				Object obj = this.data.get(param.getName());
				if(obj == null){obj = param.getValue();}
				header.put(param.getName(), obj);
			}
			Map<String,Object> body = new HashMap<String,Object>();
			for(SocketProtocolParameter param : this.protocolObject.getBodyFields()){
				Object obj = this.data.get(param.getName());
				if(obj == null){obj = param.getValue();}
				body.put(param.getName(), obj);
			}
			return JsonUtils.toJson(header) + JsonUtils.toJson(body)+"\n";
		}
		return this.originalMessage +"\n";
	}
	
	@SuppressWarnings("unchecked")
	public void readOriginalMessage(Object originalMessage) {
		Matcher mat = Pattern.compile("^(\\{[^\\}]*\\})(.*)$").matcher(originalMessage.toString());
        if(mat.find()){
        	header = JsonUtils.fromJson(mat.group(1), Map.class);
        	this.originalMessageBody = mat.group(2);
        	//body = JsonUtils.fromJson(mat.group(2), Map.class);
        }
	}

}
